# -*- coding: utf-8 -*-
"""
Created on Wed Jan 01 08:21:24 2014

@author: Casa
"""
import numpy as np
import cfunc

def __subvec(data,block_size):
    _data=[]
    size=((data.shape[1]+block_size-1)/block_size)
    for x in data:
        t=x.copy()
        t.resize(size*block_size)
        _data.append(t)
    _data=np.array(_data,np.int)
    _data.shape=(size*data.shape[0],block_size)
    return _data
    
def VSHC(data,block_size=21,enc=32,n=3):
    _block_size=block_size/n
    vecs=__subvec(data,block_size)
    vecs=cfunc.v2i(vecs)
    code,Nenc=cfunc.OSHC(vecs,block_size,enc)
    uncode=[]
    for vec in vecs:
        for i in range(code.size):
            t=code[i]^vec
            if (t&(t >> 1) & 0x5555555555555555) == 0:
                break
        if i==code.size-1:
            uncode.append(vec)
    sum=0    
    uncode=cfunc.i2v(np.array(uncode,np.int64),block_size)
    uncode=cfunc.v2i(__subvec(uncode,_block_size))    
    _code,_Nenc=cfunc.OSHC(uncode,_block_size,enc) 
    mNenc=Nenc+_Nenc
    from huffman import huffman
    h=huffman(mNenc)    
    for i in range(enc+1):
        sum+=mNenc[i]*len(h[i])
    sum+=_Nenc[-1]*_block_size
#    print 'VSHC',block_size,enc,n,1-sum*1.0/data.size
    return sum

def VSHC2(data,block_size=21,enc=32,n=3): 
    _enc=32-enc
    _block_size=block_size/n
    vecs=__subvec(data,block_size)
    vecs=cfunc.v2i(vecs)
    code,Nenc=cfunc.OSHC(vecs,block_size,enc)
    uncode=[]
    for vec in vecs:
        for i in range(code.size):
            t=code[i]^vec
            if (t&(t >> 1) & 0x5555555555555555) == 0:
                break
        if i==code.size-1:
            uncode.append(vec)
    uncode=cfunc.i2v(np.array(uncode,np.int64),block_size)
    uncode=cfunc.v2i(__subvec(uncode,_block_size))    
    _code,_Nenc=cfunc.OSHC(uncode,_block_size,_enc)
    sum=0
    from huffman import huffman
    h=huffman(Nenc)    
    for i in range(Nenc.size):
        sum+=Nenc[i]*len(h[i])
    _h=huffman(_Nenc)
    for i in range(_Nenc.size):
        sum+=_Nenc[i]*len(_h[i])
    sum+=_Nenc[-1]*_block_size
#    L=[]
#    for vec in vecs:
#        for i in range(code.size):
#            t=code[i]^vec
#            if (t&(t >> 1) & 0x55555555) == 0:
#                L.extend(h[i])
#                break
#        if i==code.size-1:
#            x=cfunc.i2v(np.array([vec]),block_size)
#            x=cfunc.v2i(x.reshape(-1,_block_size))
#            for y in x:
#                for j in range(_code.size):
#                    t=_code[j]^y
#                    if (t&(t >> 1) & 0x55555555) == 0:
#                        L.extend(_h[j])
#                        break
#                if j==_code.size-1:
#                    L.extend(cfunc.i2v(np.array([y]),_block_size)[0])
#    print 'VSHC',block_size,enc,n,1-sum*1.0/data.size
    return sum

    
if __name__=="__main__":
    from testset import testset
    ts=testset('F:/work/vlsi-test/TestDataCompression/circutes/s5378')#    ts=testset('s337')
    print ts.name
    r=VSHC2(ts.data,block_size=22,enc=17,n=2)
    print 1-r*1.0/ts.data.size